home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / bob13.arc / BOBCOM.C < prev    next >
Text File  |  1991-10-01  |  32KB  |  1,457 lines

  1. /* bobcom.c - the bytecode compiler */
  2. /*
  3.     Copyright (c) 1991, by David Michael Betz
  4.     All rights reserved
  5. */
  6.  
  7. #include <setjmp.h>
  8. #include "bob.h"
  9.  
  10. /* partial value structure */
  11. typedef struct {
  12.   int (*fcn)();
  13.   int val;
  14. } PVAL;
  15.  
  16. /* variable access function codes */
  17. #define LOAD    1
  18. #define STORE    2
  19. #define PUSH    3
  20. #define DUP    4
  21.  
  22. /* global variables */
  23. int decode=0;         /* flag for decoding functions */
  24.  
  25. /* local variables */
  26. static ARGUMENT *arguments;    /* argument list */
  27. static ARGUMENT *temporaries;    /* temporary variable list */
  28. static LITERAL *literals;    /* literal list */
  29. static VALUE methodclass;    /* class of the current method */
  30. static unsigned char *cbuff;    /* code buffer */
  31. static int cptr;        /* code pointer */
  32.  
  33. /* break/continue stacks */
  34. #define SSIZE    10
  35. static int bstack[SSIZE],*bsp;
  36. static int cstack[SSIZE],*csp;
  37.  
  38. /* external variables */
  39. extern jmp_buf error_trap;    /* trap for compile errors */
  40. extern VALUE symbols;    /* symbol table */
  41. extern VALUE classes;    /* class table */
  42. extern VALUE *sp;    /* stack pointer */
  43. extern int t_value;    /* token value */
  44. extern char t_token[];    /* token string */
  45.  
  46. /* forward declarations */
  47. CLASS *get_class();
  48. VECTOR *do_code();
  49. char *copystring();
  50. char *getmemory();
  51.  
  52. /* init_compiler - initialize the compiler */
  53. int init_compiler(cmax)
  54.   int cmax;
  55. {
  56.     char *calloc();
  57.     literals = NULL;
  58.     set_nil(&methodclass);
  59.     return ((cbuff = (unsigned char *)calloc(1,cmax)) != NULL);
  60. }
  61.  
  62. /* mark_compiler - mark compiler variables */
  63. mark_compiler()
  64. {
  65.     LITERAL *lit;
  66.     for (lit = literals; lit != NULL; lit = lit->lit_next)
  67.     mark(&lit->lit_value);
  68.     mark(&methodclass);
  69. }
  70.  
  71. /* compile_definitions - compile class or function definitions */
  72. int compile_definitions(getcf,getcd)
  73.   int (*getcf)(); void *getcd;
  74. {
  75.     char name[TKNSIZE+1];
  76.     int tkn,i;
  77.  
  78.     /* trap errors */
  79.     if (setjmp(error_trap))
  80.     return (FALSE);
  81.  
  82.     /* initialize */
  83.     init_scanner(getcf,getcd);
  84.     bsp = &bstack[-1];
  85.     csp = &cstack[-1];
  86.  
  87.     /* process statements until end of file */
  88.     while ((tkn = token()) != T_EOF) {
  89.     switch (tkn) {
  90.     case T_IDENTIFIER:
  91.         strcpy(name,t_token);
  92.         do_function(name);
  93.         break;
  94.     case T_CLASS:
  95.         do_class();
  96.         break;
  97.     default:
  98.         parse_error("Expecting a declaration");
  99.         break;
  100.     }
  101.     }
  102.     return (TRUE);
  103. }
  104.  
  105. /* do_class - handle class declarations */
  106. static int do_class()
  107. {
  108.     ARGUMENT *mvars,*smvars,*fargs,**table,*p;
  109.     char cname[TKNSIZE+1],id[TKNSIZE+1];
  110.     DICT_ENTRY *entry;
  111.     int type,tkn,i;
  112.  
  113.     /* initialize */
  114.     mvars = smvars = fargs = NULL;
  115.     check(1);
  116.     
  117.     /* get the class name */
  118.     frequire(T_IDENTIFIER);
  119.     strcpy(cname,t_token);
  120.     
  121.     /* get the optional base class */
  122.     if ((tkn = token()) == ':') {
  123.     frequire(T_IDENTIFIER);
  124.     push_class(get_class(t_token));
  125. info("Class '%s', Base class '%s'",
  126.      cname,getcstring(id,sizeof(id),clgetname(sp)));
  127.     }
  128.     else {
  129.     push_nil();
  130.     stoken(tkn);
  131. info("Class '%s'",cname);
  132.     }
  133.     frequire('{');
  134.  
  135.     /* create the new class object */
  136.     set_class(sp,newclass(cname,sp));
  137.     addentry(&classes,cname,ST_CLASS)->de_value = *sp;
  138.  
  139.     /* handle each variable declaration */
  140.     while ((tkn = token()) != '}') {
  141.  
  142.     /* check for static members */
  143.     if ((type = tkn) == T_STATIC)
  144.         tkn = token();
  145.  
  146.     /* get the first identifier */
  147.     if (tkn != T_IDENTIFIER)
  148.         parse_error("Expecting a member declaration");
  149.     strcpy(id,t_token);
  150.  
  151.     /* check for a member function declaration */
  152.     if ((tkn = token()) == '(') {
  153.         get_id_list(&fargs,")");
  154.         frequire(')');
  155.         addentry(clgetfunctions(sp),id,
  156.              type == T_STATIC ? ST_SFUNCTION : ST_FUNCTION);
  157.         freelist(&fargs);
  158.     }
  159.  
  160.     /* handle data members */
  161.     else {
  162.         table = (type == T_STATIC ? &smvars : &mvars);
  163.         addargument(table,id);
  164.         if (tkn == ',')
  165.         get_id_list(table,";");
  166.         else
  167.         stoken(tkn);
  168.     }        
  169.     frequire(';');
  170.     }
  171.  
  172.     /* store the member variable names */
  173.     i = (isnil(clgetbase(sp)) ? 0 : clgetsize(clgetbase(sp)));
  174.     for (p = mvars; p != NULL; p = p->arg_next) {
  175.     entry = addentry(clgetmembers(sp),p->arg_name,ST_DATA);
  176.     set_integer(&entry->de_value,i++);
  177.     }
  178.     sp->v.v_class->cl_size = i;
  179.     freelist(&mvars);
  180.  
  181.     /* store the static member variable names */
  182.     for (p = smvars; p != NULL; p = p->arg_next)
  183.     addentry(clgetmembers(sp),p->arg_name,ST_SDATA);
  184.     freelist(&smvars);
  185.     ++sp;
  186. }
  187.  
  188. /* findmember - find a class member */
  189. static DICT_ENTRY *findmember(class,name)
  190.   CLASS *class; char *name;
  191. {
  192.     DICT_ENTRY *entry;
  193.     if ((entry = findentry(&class->cl_members,name)) != NULL)
  194.     return (entry);
  195.     return (findentry(&class->cl_functions,name));
  196. }
  197.  
  198. /* rfindmember - recursive findmember */
  199. static DICT_ENTRY *rfindmember(class,name)
  200.   CLASS *class; char *name;
  201. {
  202.     DICT_ENTRY *entry;
  203.     if ((entry = findmember(class,name)) != NULL)
  204.     return (entry);
  205.     else if (!isnil(&class->cl_base))
  206.     return (rfindmember(claddr(&class->cl_base),name));
  207.     return (NULL);
  208. }
  209.  
  210. /* do_function - handle function declarations */
  211. static do_function(name)
  212.   char *name;
  213. {
  214.     switch (token()) {
  215.     case '(':
  216.     do_regular_function(name);
  217.     break;
  218.     case T_CC:
  219.     check(1);
  220.     push_class(get_class(name));
  221.     do_member_function(sp);
  222.     ++sp;
  223.     break;
  224.     default:
  225.     parse_error("Expecting a function declaration");
  226.     break;
  227.     }
  228. }
  229.  
  230. /* do_regular_function - parse a regular function definition */
  231. static do_regular_function(name)
  232.   char *name;
  233. {
  234.     /* enter the function name */
  235. info("Function '%s'",name);
  236.     check(1);
  237.     push_var(addentry(&symbols,name,ST_SFUNCTION));
  238.  
  239.     /* compile the body of the function */
  240.     set_bytecode(&sp->v.v_var->de_value,do_code(name,&nil));
  241.     ++sp;
  242.  
  243.     /* free the argument and temporary symbol lists */
  244.     freelist(&arguments); freelist(&temporaries);
  245. }
  246.  
  247. /* do_member_function - parse a member function definition */
  248. static do_member_function(class)
  249.   VALUE *class;
  250. {
  251.     char name[TKNSIZE+1],selector[TKNSIZE+1];
  252.     DICT_ENTRY *entry;
  253.     int tkn;
  254.     
  255.     /* get the selector */
  256.     frequire(T_IDENTIFIER);
  257.     strcpy(selector,t_token);
  258.     frequire('(');
  259. getcstring(name,sizeof(name),clgetname(class));
  260. info("Member function '%s::%s'",name,selector);
  261.  
  262.     /* make sure the type matches the declaration */
  263.     if ((entry = findmember(claddr(class),selector)) != NULL
  264.     &&  entry->de_type != ST_FUNCTION
  265.     &&  entry->de_type != ST_SFUNCTION)
  266.     parse_error("Illegal redefinition");
  267.  
  268.     /* compile the code */
  269.     check(1);
  270.     push_var(addentry(clgetfunctions(class),selector,ST_FUNCTION));
  271.     set_bytecode(&sp->v.v_var->de_value,do_code(selector,class));
  272.     ++sp;
  273.  
  274.     /* free the argument and temporary symbol lists */
  275.     freelist(&arguments); freelist(&temporaries);
  276. }
  277.  
  278. /* do_code - compile the code part of a function or method */
  279. static VECTOR *do_code(name,class)
  280.   char *name; VALUE *class;
  281. {
  282.     unsigned char *src,*dst;
  283.     int tcnt=0,nlits,tkn,i;
  284.     LITERAL *lit;
  285.  
  286.     /* initialize */
  287.     arguments = temporaries = NULL;
  288.     cptr = 0;
  289.  
  290.     /* add the implicit 'this' argument for member functions */
  291.     if (!isnil(class))
  292.     addargument(&arguments,"this");
  293.     methodclass = *class;
  294.     
  295.     /* get the argument list */
  296.     get_id_list(&arguments,";)");
  297.  
  298.     /* get temporary variables */
  299.     if ((tkn = token()) == ';') {
  300.     tcnt = get_id_list(&temporaries,")");
  301.     tkn = token();
  302.     }
  303.     require(tkn,')');
  304.     
  305.     /* reserve space for the temporaries */
  306.     if (tcnt > 0) {
  307.     putcbyte(OP_TSPACE);
  308.     putcbyte(tcnt);
  309.     }
  310.  
  311.     /* store the bytecodes, class and function name as the first literals */
  312.     addliteral(&literals,&lit);    /* will become the bytecode string */
  313.     addliteral(&literals,&lit);    /* class */
  314.     lit->lit_value = *class;
  315.     make_lit_string(name);    /* function name */
  316.  
  317.     /* compile the code */
  318.     putcbyte(OP_PUSH);
  319.     frequire('{');
  320.     do_block();
  321.     putcbyte(OP_RETURN);
  322.  
  323.     /* count the number of literals */
  324.     for (nlits = 0, lit = literals; lit != NULL; lit = lit->lit_next)
  325.     ++nlits;
  326.  
  327.     /* build the function */
  328.     check(1);
  329.     push_bytecode(newvector(nlits));
  330.     
  331.     /* create the code string */
  332.     set_string(&literals->lit_value,newstring(cptr));
  333.     src = cbuff;
  334.     dst = strgetdata(&literals->lit_value);
  335.     while (--cptr >= 0)
  336.     *dst++ = *src++;
  337.     
  338.     /* copy the literals */
  339.     for (i = 0, lit = literals; i < nlits; ++i, lit = lit->lit_next)
  340.     vecsetelement(sp,i,lit->lit_value);
  341.     freeliterals(&literals);
  342.  
  343.     /* show the generated code */
  344.     if (decode)
  345.     decode_procedure(sp);
  346.  
  347.     /* return the code object */
  348.     return (vecaddr(sp++));
  349. }
  350.  
  351. /* get_class - get the class associated with a symbol */
  352. static CLASS *get_class(name)
  353.   char *name;
  354. {
  355.     DICT_ENTRY *sym;
  356.     sym = findentry(&classes,name);
  357.     if (sym == NULL || sym->de_value.v_type != DT_CLASS)
  358.     parse_error("Expecting a class name");
  359.     return (claddr(&sym->de_value));
  360. }
  361.  
  362. /* do_statement - compile a single statement */
  363. static do_statement()
  364. {
  365.     int tkn;
  366.     switch (tkn = token()) {
  367.     case T_IF:        do_if();    break;
  368.     case T_WHILE:    do_while();    break;
  369.     case T_DO:        do_dowhile();    break;
  370.     case T_FOR:        do_for();    break;
  371.     case T_BREAK:    do_break();    break;
  372.     case T_CONTINUE:    do_continue();    break;
  373.     case T_RETURN:    do_return();    break;
  374.     case '{':        do_block();    break;
  375.     case ';':        ;        break;
  376.     default:        stoken(tkn);
  377.             do_expr();
  378.             frequire(';');  break;
  379.     }
  380. }
  381.  
  382. /* do_if - compile the IF/ELSE expression */
  383. static do_if()
  384. {
  385.     int tkn,nxt,end;
  386.  
  387.     /* compile the test expression */
  388.     do_test();
  389.  
  390.     /* skip around the 'then' clause if the expression is false */
  391.     putcbyte(OP_BRF);
  392.     nxt = putcword(0);
  393.  
  394.     /* compile the 'then' clause */
  395.     do_statement();
  396.  
  397.     /* compile the 'else' clause */
  398.     if ((tkn = token()) == T_ELSE) {
  399.     putcbyte(OP_BR);
  400.     end = putcword(0);
  401.     fixup(nxt,cptr);
  402.     do_statement();
  403.     nxt = end;
  404.     }
  405.     else
  406.     stoken(tkn);
  407.  
  408.     /* handle the end of the statement */
  409.     fixup(nxt,cptr);
  410. }
  411.  
  412. /* addbreak - add a break level to the stack */
  413. static int *addbreak(lbl)
  414.   int lbl;
  415. {
  416.     int *old=bsp;
  417.     if (++bsp < &bstack[SSIZE])
  418.     *bsp = lbl;
  419.     else
  420.     parse_error("Too many nested loops");
  421.     return (old);
  422. }
  423.  
  424. /* rembreak - remove a break level from the stack */
  425. static int rembreak(old,lbl)
  426.   int *old,lbl;
  427. {
  428.    return (bsp > old ? *bsp-- : lbl);
  429. }
  430.  
  431. /* addcontinue - add a continue level to the stack */
  432. static int *addcontinue(lbl)
  433.   int lbl;
  434. {
  435.     int *old=csp;
  436.     if (++csp < &cstack[SSIZE])
  437.     *csp = lbl;
  438.     else
  439.     parse_error("Too many nested loops");
  440.     return (old);
  441. }
  442.  
  443. /* remcontinue - remove a continue level from the stack */
  444. static remcontinue(old)
  445.   int *old;
  446. {
  447.     csp = old;
  448. }
  449.  
  450. /* do_while - compile the WHILE expression */
  451. static do_while()
  452. {
  453.     int nxt,end,*ob,*oc;
  454.  
  455.     /* compile the test expression */
  456.     nxt = cptr;
  457.     do_test();
  458.  
  459.     /* skip around the loop body if the expression is false */
  460.     putcbyte(OP_BRF);
  461.     end = putcword(0);
  462.  
  463.     /* compile the loop body */
  464.     ob = addbreak(end);
  465.     oc = addcontinue(nxt);
  466.     do_statement();
  467.     end = rembreak(ob,end);
  468.     remcontinue(oc);
  469.  
  470.     /* branch back to the start of the loop */
  471.     putcbyte(OP_BR);
  472.     putcword(nxt);
  473.  
  474.     /* handle the end of the statement */
  475.     fixup(end,cptr);
  476. }
  477.  
  478. /* do_dowhile - compile the DO/WHILE expression */
  479. static do_dowhile()
  480. {
  481.     int nxt,end=0,*ob,*oc;
  482.  
  483.     /* remember the start of the loop */
  484.     nxt = cptr;
  485.  
  486.     /* compile the loop body */
  487.     ob = addbreak(0);
  488.     oc = addcontinue(nxt);
  489.     do_statement();
  490.     end = rembreak(ob,end);
  491.     remcontinue(oc);
  492.  
  493.     /* compile the test expression */
  494.     frequire(T_WHILE);
  495.     do_test();
  496.     frequire(';');
  497.  
  498.     /* branch to the top if the expression is true */
  499.     putcbyte(OP_BRT);
  500.     putcword(nxt);
  501.  
  502.     /* handle the end of the statement */
  503.     fixup(end,cptr);
  504. }
  505.  
  506. /* do_for - compile the FOR statement */
  507. static do_for()
  508. {
  509.     int tkn,nxt,end,body,update,*ob,*oc;
  510.  
  511.     /* compile the initialization expression */
  512.     frequire('(');
  513.     if ((tkn = token()) != ';') {
  514.     stoken(tkn);
  515.     do_expr();
  516.     frequire(';');
  517.     }
  518.  
  519.     /* compile the test expression */
  520.     nxt = cptr;
  521.     if ((tkn = token()) != ';') {
  522.     stoken(tkn);
  523.     do_expr();
  524.     frequire(';');
  525.     }
  526.  
  527.     /* branch to the loop body if the expression is true */
  528.     putcbyte(OP_BRT);
  529.     body = putcword(0);
  530.  
  531.     /* branch to the end if the expression is false */
  532.     putcbyte(OP_BR);
  533.     end = putcword(0);
  534.  
  535.     /* compile the update expression */
  536.     update = cptr;
  537.     if ((tkn = token()) != ')') {
  538.     stoken(tkn);
  539.     do_expr();
  540.     frequire(')');
  541.     }
  542.  
  543.     /* branch back to the test code */
  544.     putcbyte(OP_BR);
  545.     putcword(nxt);
  546.  
  547.     /* compile the loop body */
  548.     fixup(body,cptr);
  549.     ob = addbreak(end);
  550.     oc = addcontinue(update);
  551.     do_statement();
  552.     end = rembreak(ob,end);
  553.     remcontinue(oc);
  554.  
  555.     /* branch back to the update code */
  556.     putcbyte(OP_BR);
  557.     putcword(update);
  558.  
  559.     /* handle the end of the statement */
  560.     fixup(end,cptr);
  561. }
  562.  
  563. /* do_break - compile the BREAK statement */
  564. static do_break()
  565. {
  566.     if (bsp >= bstack) {
  567.     putcbyte(OP_BR);
  568.     *bsp = putcword(*bsp);
  569.     }
  570.     else
  571.     parse_error("Break outside of loop");
  572. }
  573.  
  574. /* do_continue - compile the CONTINUE statement */
  575. static do_continue()
  576. {
  577.     if (csp >= cstack) {
  578.     putcbyte(OP_BR);
  579.     putcword(*csp);
  580.     }
  581.     else
  582.     parse_error("Continue outside of loop");
  583. }
  584.  
  585. /* do_block - compile the {} expression */
  586. static do_block()
  587. {
  588.     int tkn;
  589.     if ((tkn = token()) != '}') {
  590.     do {
  591.         stoken(tkn);
  592.         do_statement();
  593.     } while ((tkn = token()) != '}');
  594.     }
  595.     else
  596.     putcbyte(OP_NIL);
  597. }
  598.  
  599. /* do_return - handle the RETURN expression */
  600. static do_return()
  601. {
  602.     do_expr();
  603.     frequire(';');
  604.     putcbyte(OP_RETURN);
  605. }
  606.  
  607. /* do_test - compile a test expression */
  608. static do_test()
  609. {
  610.     frequire('(');
  611.     do_expr();
  612.     frequire(')');
  613. }
  614.  
  615. /* do_expr - parse an expression */
  616. static do_expr()
  617. {
  618.     PVAL pv;
  619.     do_expr1(&pv);
  620.     rvalue(&pv);
  621. }
  622.  
  623. /* rvalue - get the rvalue of a partial expression */
  624. static rvalue(pv)
  625.   PVAL *pv;
  626. {
  627.     if (pv->fcn) {
  628.     (*pv->fcn)(LOAD,pv->val);
  629.     pv->fcn = NULL;
  630.     }
  631. }
  632.  
  633. /* chklvalue - make sure we've got an lvalue */
  634. static chklvalue(pv)
  635.   PVAL *pv;
  636. {
  637.     if (pv->fcn == NULL)
  638.     parse_error("Expecting an lvalue");
  639. }
  640.  
  641. /* do_expr1 - handle the ',' operator */
  642. static do_expr1(pv)
  643.   PVAL *pv;
  644. {
  645.     int tkn;
  646.     do_expr2(pv);
  647.     while ((tkn = token()) == ',') {
  648.     rvalue(pv);
  649.     do_expr1(pv); rvalue(pv);
  650.     }
  651.     stoken(tkn);
  652. }
  653.  
  654. /* do_expr2 - handle the assignment operators */
  655. static do_expr2(pv)
  656.   PVAL *pv;
  657. {
  658.     int tkn,nxt,end;
  659.     PVAL rhs;
  660.     do_expr3(pv);
  661.     while ((tkn = token()) == '='
  662.     ||     tkn == T_ADDEQ || tkn == T_SUBEQ
  663.     ||     tkn == T_MULEQ || tkn == T_DIVEQ || tkn == T_REMEQ
  664.     ||     tkn == T_ANDEQ || tkn == T_OREQ  || tkn == T_XOREQ
  665.     ||     tkn == T_SHLEQ || tkn == T_SHLEQ) {
  666.     chklvalue(pv);
  667.     switch (tkn) {
  668.     case '=':
  669.         (*pv->fcn)(PUSH);
  670.         do_expr1(&rhs); rvalue(&rhs);
  671.         (*pv->fcn)(STORE,pv->val);
  672.         break;
  673.     case T_ADDEQ:        do_assignment(pv,OP_ADD);        break;
  674.     case T_SUBEQ:        do_assignment(pv,OP_SUB);        break;
  675.     case T_MULEQ:        do_assignment(pv,OP_MUL);        break;
  676.     case T_DIVEQ:        do_assignment(pv,OP_DIV);        break;
  677.     case T_REMEQ:        do_assignment(pv,OP_REM);        break;
  678.     case T_ANDEQ:        do_assignment(pv,OP_BAND);        break;
  679.     case T_OREQ:        do_assignment(pv,OP_BOR);        break;
  680.     case T_XOREQ:        do_assignment(pv,OP_XOR);        break;
  681.     case T_SHLEQ:        do_assignment(pv,OP_SHL);        break;
  682.     case T_SHREQ:        do_assignment(pv,OP_SHR);        break;
  683.      }
  684.     pv->fcn = NULL;
  685.     }
  686.     stoken(tkn);
  687. }
  688.  
  689. /* do_assignment - handle assignment operations */
  690. static do_assignment(pv,op)
  691.   PVAL *pv; int op;
  692. {
  693.     PVAL rhs;
  694.     (*pv->fcn)(DUP);
  695.     (*pv->fcn)(LOAD,pv->val);
  696.     putcbyte(OP_PUSH);
  697.     do_expr1(&rhs); rvalue(&rhs);
  698.     putcbyte(op);
  699.     (*pv->fcn)(STORE,pv->val);
  700. }
  701.  
  702. /* do_expr3 - handle the '?:' operator */
  703. static do_expr3(pv)
  704.   PVAL *pv;
  705. {
  706.     int tkn,nxt,end;
  707.     do_expr4(pv);
  708.     while ((tkn = token()) == '?') {
  709.     rvalue(pv);
  710.     putcbyte(OP_BRF);
  711.     nxt = putcword(0);
  712.     do_expr1(pv); rvalue(pv);
  713.     frequire(':');
  714.     putcbyte(OP_BR);
  715.     end = putcword(0);
  716.     fixup(nxt,cptr);
  717.     do_expr1(pv); rvalue(pv);
  718.     fixup(end,cptr);
  719.     }
  720.     stoken(tkn);
  721. }
  722.  
  723. /* do_expr4 - handle the '||' operator */
  724. static do_expr4(pv)
  725.   PVAL *pv;
  726. {
  727.     int tkn,end=0;
  728.     do_expr5(pv);
  729.     while ((tkn = token()) == T_OR) {
  730.     rvalue(pv);
  731.     putcbyte(OP_BRT);
  732.     end = putcword(end);
  733.     do_expr5(pv); rvalue(pv);
  734.     }
  735.     fixup(end,cptr);
  736.     stoken(tkn);
  737. }
  738.  
  739. /* do_expr5 - handle the '&&' operator */
  740. static do_expr5(pv)
  741.   PVAL *pv;
  742. {
  743.     int tkn,end=0;
  744.     do_expr6(pv);
  745.     while ((tkn = token()) == T_AND) {
  746.     rvalue(pv);
  747.     putcbyte(OP_BRF);
  748.     end = putcword(end);
  749.     do_expr6(pv); rvalue(pv);
  750.     }
  751.     fixup(end,cptr);
  752.     stoken(tkn);
  753. }
  754.  
  755. /* do_expr6 - handle the '|' operator */
  756. static do_expr6(pv)
  757.   PVAL *pv;
  758. {
  759.     int tkn;
  760.     do_expr7(pv);
  761.     while ((tkn = token()) == '|') {
  762.     rvalue(pv);
  763.     putcbyte(OP_PUSH);
  764.     do_expr7(pv); rvalue(pv);
  765.     putcbyte(OP_BOR);
  766.     }
  767.     stoken(tkn);
  768. }
  769.  
  770. /* do_expr7 - handle the '^' operator */
  771. static do_expr7(pv)
  772.   PVAL *pv;
  773. {
  774.     int tkn;
  775.     do_expr8(pv);
  776.     while ((tkn = token()) == '^') {
  777.     rvalue(pv);
  778.     putcbyte(OP_PUSH);
  779.     do_expr8(pv); rvalue(pv);
  780.     putcbyte(OP_XOR);
  781.     }
  782.     stoken(tkn);
  783. }
  784.  
  785. /* do_expr8 - handle the '&' operator */
  786. static do_expr8(pv)
  787.   PVAL *pv;
  788. {
  789.     int tkn;
  790.     do_expr9(pv);
  791.     while ((tkn = token()) == '&') {
  792.     rvalue(pv);
  793.     putcbyte(OP_PUSH);
  794.     do_expr9(pv); rvalue(pv);
  795.     putcbyte(OP_BAND);
  796.     }
  797.     stoken(tkn);
  798. }
  799.  
  800. /* do_expr9 - handle the '==' and '!=' operators */
  801. static do_expr9(pv)
  802.   PVAL *pv;
  803. {
  804.     int tkn,op;
  805.     do_expr10(pv);
  806.     while ((tkn = token()) == T_EQ || tkn == T_NE) {
  807.     switch (tkn) {
  808.     case T_EQ: op = OP_EQ; break;
  809.     case T_NE: op = OP_NE; break;
  810.     }
  811.     rvalue(pv);
  812.     putcbyte(OP_PUSH);
  813.     do_expr10(pv); rvalue(pv);
  814.     putcbyte(op);
  815.     }
  816.     stoken(tkn);
  817. }
  818.  
  819. /* do_expr10 - handle the '<', '<=', '>=' and '>' operators */
  820. static do_expr10(pv)
  821.   PVAL *pv;
  822. {
  823.     int tkn,op;
  824.     do_expr11(pv);
  825.     while ((tkn = token()) == '<' || tkn == T_LE || tkn == T_GE || tkn == '>') {
  826.     switch (tkn) {
  827.     case '<':  op = OP_LT; break;
  828.     case T_LE: op = OP_LE; break;
  829.     case T_GE: op = OP_GE; break;
  830.     case '>':  op = OP_GT; break;
  831.     }
  832.     rvalue(pv);
  833.     putcbyte(OP_PUSH);
  834.     do_expr11(pv); rvalue(pv);
  835.     putcbyte(op);
  836.     }
  837.     stoken(tkn);
  838. }
  839.  
  840. /* do_expr11 - handle the '<<' and '>>' operators */
  841. static do_expr11(pv)
  842.   PVAL *pv;
  843. {
  844.     int tkn,op;
  845.     do_expr12(pv);
  846.     while ((tkn = token()) == T_SHL || tkn == T_SHR) {
  847.     switch (tkn) {
  848.     case T_SHL: op = OP_SHL; break;
  849.     case T_SHR: op = OP_SHR; break;
  850.     }
  851.     rvalue(pv);
  852.     putcbyte(OP_PUSH);
  853.     do_expr12(pv); rvalue(pv);
  854.     putcbyte(op);
  855.     }
  856.     stoken(tkn);
  857. }
  858.  
  859. /* do_expr12 - handle the '+' and '-' operators */
  860. static do_expr12(pv)
  861.   PVAL *pv;
  862. {
  863.     int tkn,op;
  864.     do_expr13(pv);
  865.     while ((tkn = token()) == '+' || tkn == '-') {
  866.     switch (tkn) {
  867.     case '+': op = OP_ADD; break;
  868.     case '-': op = OP_SUB; break;
  869.     }
  870.     rvalue(pv);
  871.     putcbyte(OP_PUSH);
  872.     do_expr13(pv); rvalue(pv);
  873.     putcbyte(op);
  874.     }
  875.     stoken(tkn);
  876. }
  877.  
  878. /* do_expr13 - handle the '*' and '/' operators */
  879. static do_expr13(pv)
  880.   PVAL *pv;
  881. {
  882.     int tkn,op;
  883.     do_expr14(pv);
  884.     while ((tkn = token()) == '*' || tkn == '/' || tkn == '%') {
  885.     switch (tkn) {
  886.     case '*': op = OP_MUL; break;
  887.     case '/': op = OP_DIV; break;
  888.     case '%': op = OP_REM; break;
  889.     }
  890.     rvalue(pv);
  891.     putcbyte(OP_PUSH);
  892.     do_expr14(pv); rvalue(pv);
  893.     putcbyte(op);
  894.     }
  895.     stoken(tkn);
  896. }
  897.  
  898. /* do_expr14 - handle unary operators */
  899. static do_expr14(pv)
  900.   PVAL *pv;
  901. {
  902.     int tkn;
  903.     switch (tkn = token()) {
  904.     case '-':
  905.     do_expr15(pv); rvalue(pv);
  906.     putcbyte(OP_NEG);
  907.     break;
  908.     case '!':
  909.     do_expr15(pv); rvalue(pv);
  910.     putcbyte(OP_NOT);
  911.     break;
  912.     case '~':
  913.     do_expr15(pv); rvalue(pv);
  914.     putcbyte(OP_BNOT);
  915.     break;
  916.     case T_INC:
  917.     do_preincrement(pv,OP_INC);
  918.     break;
  919.     case T_DEC:
  920.     do_preincrement(pv,OP_DEC);
  921.     break;
  922.     case T_NEW:
  923.     do_new(pv);
  924.     break;
  925.     default:
  926.     stoken(tkn);
  927.     do_expr15(pv);
  928.     return;
  929.     }
  930. }
  931.  
  932. /* do_preincrement - handle prefix '++' and '--' */
  933. static do_preincrement(pv,op)
  934.   PVAL *pv;
  935. {
  936.     do_expr15(pv);
  937.     chklvalue(pv);
  938.     (*pv->fcn)(DUP);
  939.     (*pv->fcn)(LOAD,pv->val);
  940.     putcbyte(op);
  941.     (*pv->fcn)(STORE,pv->val);
  942.     pv->fcn = NULL;
  943. }
  944.  
  945. /* do_postincrement - handle postfix '++' and '--' */
  946. static do_postincrement(pv,op)
  947.   PVAL *pv;
  948. {
  949.     chklvalue(pv);
  950.     (*pv->fcn)(DUP);
  951.     (*pv->fcn)(LOAD,pv->val);
  952.     putcbyte(op);
  953.     (*pv->fcn)(STORE,pv->val);
  954.     putcbyte(op == OP_INC ? OP_DEC : OP_INC);
  955.     pv->fcn = NULL;
  956. }
  957.  
  958. /* do_new - handle the 'new' operator */
  959. static do_new(pv)
  960.   PVAL *pv;
  961. {
  962.     char selector[TKNSIZE+1];
  963.     LITERAL *lit;
  964.     CLASS *class;
  965.  
  966.     frequire(T_IDENTIFIER);
  967.     strcpy(selector,t_token);
  968.  
  969.     class = get_class(selector);
  970.  
  971.     code_literal(addliteral(&literals,&lit));
  972.     set_class(&lit->lit_value,class);
  973.  
  974.     putcbyte(OP_NEW);
  975.     pv->fcn = NULL;
  976.     
  977.     do_send(selector,pv);
  978. }
  979.  
  980. /* do_expr15 - handle function calls */
  981. static do_expr15(pv)
  982.   PVAL *pv;
  983. {
  984.     char selector[TKNSIZE+1];
  985.     int tkn;
  986.     do_primary(pv);
  987.     while ((tkn = token()) == '('
  988.     ||     tkn == '['
  989.     ||     tkn == T_MEMREF
  990.     ||     tkn == T_INC
  991.     ||     tkn == T_DEC)
  992.     switch (tkn) {
  993.     case '(':
  994.         do_call(pv);
  995.         break;
  996.     case '[':
  997.         do_index(pv);
  998.         break;
  999.     case T_MEMREF:
  1000.         frequire(T_IDENTIFIER);
  1001.         strcpy(selector,t_token);
  1002.         do_send(selector,pv);
  1003.         break;
  1004.     case T_INC:
  1005.         do_postincrement(pv,OP_INC);
  1006.         break;
  1007.     case T_DEC:
  1008.         do_postincrement(pv,OP_DEC);
  1009.         break;
  1010.     }
  1011.     stoken(tkn);
  1012. }
  1013.  
  1014. /* do_primary - parse a primary expression and unary operators */
  1015. static do_primary(pv)
  1016.   PVAL *pv;
  1017. {
  1018.     char id[TKNSIZE+1];
  1019.     DICT_ENTRY *entry;
  1020.     CLASS *class;
  1021.     int tkn;
  1022.     switch (token()) {
  1023.     case '(':
  1024.     do_expr1(pv);
  1025.     frequire(')');
  1026.     break;
  1027.     case T_NUMBER:
  1028.     do_lit_integer((long)t_value);
  1029.     pv->fcn = NULL;
  1030.     break;
  1031.     case T_STRING:
  1032.     do_lit_string(t_token);
  1033.     pv->fcn = NULL;
  1034.     break;
  1035.     case T_NIL:
  1036.     putcbyte(OP_NIL);
  1037.     break;
  1038.     case T_IDENTIFIER:
  1039.     strcpy(id,t_token);
  1040.     if ((tkn = token()) == T_CC) {
  1041.         class = get_class(id);
  1042.         frequire(T_IDENTIFIER);
  1043.         if (!findclassvariable(class,t_token,pv))
  1044.         parse_error("Not a class member");
  1045.     }
  1046.     else {
  1047.         stoken(tkn);
  1048.         findvariable(id,pv);
  1049.     }
  1050.     break;
  1051.     default:
  1052.     parse_error("Expecting a primary expression");
  1053.     break;
  1054.     }
  1055. }
  1056.  
  1057. /* do_call - compile a function call */
  1058. static do_call(pv)
  1059.   PVAL *pv;
  1060. {
  1061.     int tkn,n=0;
  1062.     
  1063.     /* get the value of the function */
  1064.     rvalue(pv);
  1065.  
  1066.     /* compile each argument expression */
  1067.     if ((tkn = token()) != ')') {
  1068.     stoken(tkn);
  1069.     do {
  1070.         putcbyte(OP_PUSH);
  1071.         do_expr2(pv); rvalue(pv);
  1072.         ++n;
  1073.     } while ((tkn = token()) == ',');
  1074.     }
  1075.     require(tkn,')');
  1076.     putcbyte(OP_CALL);
  1077.     putcbyte(n);
  1078.  
  1079.     /* we've got an rvalue now */
  1080.     pv->fcn = NULL;
  1081. }
  1082.  
  1083. /* do_send - compile a message sending expression */
  1084. static do_send(selector,pv)
  1085.   char *selector; PVAL *pv;
  1086. {
  1087.     LITERAL *lit;
  1088.     int tkn,n=1;
  1089.     
  1090.     /* get the receiver value */
  1091.     rvalue(pv);
  1092.  
  1093.     /* generate code to push the selector */
  1094.     putcbyte(OP_PUSH);
  1095.     code_literal(addliteral(&literals,&lit));
  1096.     set_string(&lit->lit_value,makestring(selector));
  1097.  
  1098.     /* compile the argument list */
  1099.     frequire('(');
  1100.     if ((tkn = token()) != ')') {
  1101.     stoken(tkn);
  1102.     do {
  1103.         putcbyte(OP_PUSH);
  1104.         do_expr2(pv); rvalue(pv);
  1105.         ++n;
  1106.     } while ((tkn = token()) == ',');
  1107.     }
  1108.     require(tkn,')');
  1109.  
  1110.     /* send the message */
  1111.     putcbyte(OP_SEND);
  1112.     putcbyte(n);
  1113.  
  1114.     /* we've got an rvalue now */
  1115.     pv->fcn = NULL;
  1116. }
  1117.  
  1118. /* do_index - compile an indexing operation */
  1119. static do_index(pv)
  1120.   PVAL *pv;
  1121. {
  1122.     int code_index();
  1123.     rvalue(pv);
  1124.     putcbyte(OP_PUSH);
  1125.     do_expr(pv);
  1126.     frequire(']');
  1127.     pv->fcn = code_index;
  1128. }
  1129.  
  1130. /* get_id_list - get a comma separated list of identifiers */
  1131. static int get_id_list(list,term)
  1132.   ARGUMENT **list; char *term;
  1133. {
  1134.     char *strchr();
  1135.     int tkn,cnt=0;
  1136.     tkn = token();
  1137.     if (!strchr(term,tkn)) {
  1138.     stoken(tkn);
  1139.     do {
  1140.         frequire(T_IDENTIFIER);
  1141.         addargument(list,t_token);
  1142.         ++cnt;
  1143.     } while ((tkn = token()) == ',');
  1144.     }
  1145.     stoken(tkn);
  1146.     return (cnt);
  1147. }
  1148.  
  1149. /* addargument - add a formal argument */
  1150. static addargument(list,name)
  1151.   ARGUMENT **list; char *name;
  1152. {
  1153.     ARGUMENT *arg;
  1154.     arg = (ARGUMENT *)getmemory(sizeof(ARGUMENT));
  1155.     arg->arg_name = copystring(name);
  1156.     arg->arg_next = *list;
  1157.     *list = arg;
  1158. }
  1159.  
  1160. /* freelist - free a list of arguments or temporaries */
  1161. static freelist(plist)
  1162.   ARGUMENT **plist;
  1163. {
  1164.     ARGUMENT *this,*next;
  1165.     for (this = *plist, *plist = NULL; this != NULL; this = next) {
  1166.     next = this->arg_next;
  1167.     free(this->arg_name);
  1168.     free(this);
  1169.     }
  1170. }
  1171.  
  1172. /* findarg - find an argument offset */
  1173. static int findarg(name)
  1174.   char *name;
  1175. {
  1176.     ARGUMENT *arg;
  1177.     int n;
  1178.     for (n = 0, arg = arguments; arg; n++, arg = arg->arg_next)
  1179.     if (strcmp(name,arg->arg_name) == 0)
  1180.         return (n);
  1181.     return (-1);
  1182. }
  1183.  
  1184. /* findtmp - find a temporary variable offset */
  1185. static int findtmp(name)
  1186.   char *name;
  1187. {
  1188.     ARGUMENT *tmp;
  1189.     int n;
  1190.     for (n = 0, tmp = temporaries; tmp; n++, tmp = tmp->arg_next)
  1191.     if (strcmp(name,tmp->arg_name) == 0)
  1192.         return (n);
  1193.     return (-1);
  1194. }
  1195.  
  1196. /* finddatamember - find a class data member */
  1197. static DICT_ENTRY *finddatamember(name)
  1198.   char *name;
  1199. {
  1200.     DICT_ENTRY *entry;
  1201.     VALUE *class;
  1202.     if (!isnil(class)) {
  1203.     class = &methodclass;
  1204.     do {
  1205.         if ((entry = findentry(clgetmembers(class),name)) != NULL)
  1206.         return (entry);
  1207.         class = clgetbase(class);
  1208.     } while (!isnil(class));
  1209.     }
  1210.     return (NULL);
  1211. }
  1212.  
  1213. /* addliteral - add a literal */
  1214. static int addliteral(list,pval)
  1215.   LITERAL **list,**pval;
  1216. {
  1217.     LITERAL **plit,*lit;
  1218.     int n=0;
  1219.     for (plit = list; (lit = *plit) != NULL; plit = &lit->lit_next)
  1220.     ++n;
  1221.     lit = (LITERAL *)getmemory(sizeof(LITERAL));
  1222.     set_nil(&lit->lit_value);
  1223.     lit->lit_next = NULL;
  1224.     *pval = *plit = lit;
  1225.     return (n);
  1226. }
  1227.  
  1228. /* freeliterals - free a list of literals */
  1229. static freeliterals(plist)
  1230.   LITERAL **plist;
  1231. {
  1232.     LITERAL *this,*next;
  1233.     for (this = *plist, *plist = NULL; this != NULL; this = next) {
  1234.     next = this->lit_next;
  1235.     free(this);
  1236.     }
  1237. }
  1238.  
  1239. /* frequire - fetch a token and check it */
  1240. static frequire(rtkn)
  1241.   int rtkn;
  1242. {
  1243.     require(token(),rtkn);
  1244. }
  1245.  
  1246. /* require - check for a required token */
  1247. static require(tkn,rtkn)
  1248.   int tkn,rtkn;
  1249. {
  1250.     char msg[100],tknbuf[100],*tkn_name();
  1251.     if (tkn != rtkn) {
  1252.     strcpy(tknbuf,tkn_name(rtkn));
  1253.     sprintf(msg,"Expecting '%s', found '%s'",tknbuf,tkn_name(tkn));
  1254.     parse_error(msg);
  1255.     }
  1256. }
  1257.  
  1258. /* do_lit_integer - compile a literal integer */
  1259. static do_lit_integer(n)
  1260.   long n;
  1261. {
  1262.     LITERAL *lit;
  1263.     code_literal(addliteral(&literals,&lit));
  1264.     set_integer(&lit->lit_value,n);
  1265. }
  1266.  
  1267. /* do_lit_string - compile a literal string */
  1268. static do_lit_string(str)
  1269.   char *str;
  1270. {
  1271.     code_literal(make_lit_string(str));
  1272. }
  1273.  
  1274. /* make_lit_string - make a literal string */
  1275. static int make_lit_string(str)
  1276.   char *str;
  1277. {
  1278.     LITERAL *lit;
  1279.     int n;
  1280.     n = addliteral(&literals,&lit);
  1281.     set_string(&lit->lit_value,makestring(str));
  1282.     return (n);
  1283. }
  1284.  
  1285. /* make_lit_variable - make a literal reference to a variable */
  1286. static int make_lit_variable(sym)
  1287.   DICT_ENTRY *sym;
  1288. {
  1289.     LITERAL *lit;
  1290.     int n;
  1291.     n = addliteral(&literals,&lit);
  1292.     set_var(&lit->lit_value,sym);
  1293.     return (n);
  1294. }
  1295.  
  1296. /* findvariable - find a variable */
  1297. static findvariable(id,pv)
  1298.   char *id; PVAL *pv;
  1299. {    
  1300.     int code_argument(),code_temporary(),code_variable();
  1301.     DICT_ENTRY *entry;
  1302.     int n;
  1303.     if ((n = findarg(id)) >= 0) {
  1304.     pv->fcn = code_argument;
  1305.     pv->val = n;
  1306.     }
  1307.     else if ((n = findtmp(id)) >= 0) {
  1308.     pv->fcn = code_temporary;
  1309.     pv->val = n;
  1310.     }
  1311.     else if (isnil(&methodclass)
  1312.           || !findclassvariable(claddr(&methodclass),id,pv)) {
  1313.     pv->fcn = code_variable;
  1314.     pv->val = make_lit_variable(addentry(&symbols,id,ST_SDATA));
  1315.     }
  1316. }
  1317.  
  1318. /* findclassvariable - find a class member variable */
  1319. static int findclassvariable(class,name,pv)
  1320.   CLASS *class; char *name; PVAL *pv;
  1321. {
  1322.     int code_member(),code_variable();
  1323.     DICT_ENTRY *entry;
  1324.     if ((entry = rfindmember(class,name)) == NULL)
  1325.     return (FALSE);
  1326.     switch (entry->de_type) {
  1327.     case ST_DATA:
  1328.     pv->fcn = code_member;
  1329.     pv->val = entry->de_value.v.v_integer;
  1330.     break;
  1331.     case ST_SDATA:
  1332.     pv->fcn = code_variable;
  1333.            pv->val = make_lit_variable(entry);
  1334.     break;
  1335.     case ST_FUNCTION:
  1336.     findvariable("this",pv);
  1337.     do_send(name,pv);
  1338.     break;
  1339.     case ST_SFUNCTION:
  1340.     code_variable(LOAD,make_lit_variable(entry));
  1341.     pv->fcn = NULL;
  1342.     break;
  1343.     }
  1344.     return (TRUE);
  1345. }
  1346.  
  1347. /* code_argument - compile an argument reference */
  1348. static code_argument(fcn,n)
  1349.   int fcn,n;
  1350. {
  1351.     switch (fcn) {
  1352.     case LOAD:    putcbyte(OP_AREF); putcbyte(n); break;
  1353.     case STORE:    putcbyte(OP_ASET); putcbyte(n); break;
  1354.     }
  1355. }
  1356.  
  1357. /* code_temporary - compile a temporary variable reference */
  1358. static code_temporary(fcn,n)
  1359.   int fcn,n;
  1360. {
  1361.     switch (fcn) {
  1362.     case LOAD:    putcbyte(OP_TREF); putcbyte(n); break;
  1363.     case STORE:    putcbyte(OP_TSET); putcbyte(n); break;
  1364.     }
  1365. }
  1366.  
  1367. /* code_member - compile a data member reference */
  1368. static code_member(fcn,n)
  1369.   int fcn,n;
  1370. {
  1371.     switch (fcn) {
  1372.     case LOAD:    putcbyte(OP_MREF); putcbyte(n); break;
  1373.     case STORE:    putcbyte(OP_MSET); putcbyte(n); break;
  1374.     }
  1375. }
  1376.  
  1377. /* code_variable - compile a variable reference */
  1378. static code_variable(fcn,n)
  1379.   int fcn,n;
  1380. {
  1381.     switch (fcn) {
  1382.     case LOAD:    putcbyte(OP_REF); putcbyte(n); break;
  1383.     case STORE:    putcbyte(OP_SET); putcbyte(n); break;
  1384.     }
  1385. }
  1386.  
  1387. /* code_index - compile an indexed reference */
  1388. static code_index(fcn)
  1389.   int fcn;
  1390. {
  1391.     switch (fcn) {
  1392.     case LOAD:    putcbyte(OP_VREF); break;
  1393.     case STORE:    putcbyte(OP_VSET); break;
  1394.     case PUSH:  putcbyte(OP_PUSH); break;
  1395.     case DUP:    putcbyte(OP_DUP2); break;
  1396.     }
  1397. }
  1398.  
  1399. /* code_literal - compile a literal reference */
  1400. static code_literal(n)
  1401.   int n;
  1402. {
  1403.     putcbyte(OP_LIT);
  1404.     putcbyte(n);
  1405. }
  1406.  
  1407. /* putcbyte - put a code byte into data space */
  1408. static int putcbyte(b)
  1409.   int b;
  1410. {
  1411.     if (cptr >= CMAX)
  1412.     parse_error("Insufficient code space");
  1413.     cbuff[cptr] = b;
  1414.     return (cptr++);
  1415. }
  1416.  
  1417. /* putcword - put a code word into data space */
  1418. static int putcword(w)
  1419.   int w;
  1420. {
  1421.     putcbyte(w);
  1422.     putcbyte(w >> 8);
  1423.     return (cptr-2);
  1424. }
  1425.  
  1426. /* fixup - fixup a reference chain */
  1427. static fixup(chn,val)
  1428.   int chn,val;
  1429. {
  1430.     int hval,nxt;
  1431.     for (hval = val >> 8; chn != 0; chn = nxt) {
  1432.     nxt = (cbuff[chn] & 0xFF) | (cbuff[chn+1] << 8);
  1433.     cbuff[chn] = val;
  1434.     cbuff[chn+1] = hval;
  1435.     }
  1436. }
  1437.  
  1438. /* copystring - make a copy of a string */
  1439. static char *copystring(str)
  1440.   char *str;
  1441. {
  1442.     char *val;
  1443.     val = getmemory(strlen(str)+1);
  1444.     strcpy(val,str);
  1445.     return (val);
  1446. }
  1447.  
  1448. /* getmemory - allocate memory and complain if there isn't enough */
  1449. static char *getmemory(size)
  1450.   int size;
  1451. {
  1452.     char *calloc(),*val;
  1453.     if ((val = calloc(1,size)) == NULL)
  1454.     error("Insufficient memory");
  1455.     return (val);
  1456. }
  1457.